<?php

class App_Router_Http extends Mozg_Router_Protocol
{
	private $_moduleRouter;
	private $_ctrlRouter = array();

	private function GetCtrlRouter($moduleName)
	{
		if (!$this->_ctrlRouter[$moduleName])
		{
			$className = 'App_Module_' .$moduleName. '_Router_Http';
			$this->_ctrlRouter[$moduleName] = new $className();
		}
		return $this->_ctrlRouter[$moduleName];
	}

	private function GetModuleRouter()
	{
		if (!$this->_moduleRouter)
		{
			$this->_moduleRouter = new App_Router_Http_Module();
		}
		return $this->_moduleRouter;
	}

	public function Create($elements = array(), $buildParams = true, &$params = array())
	{
		if (is_string($elements)) $elements = $this->ParseUrl($elements);

		$elements = (array)$elements;
		$urlParts = array_reverse($this->Build($elements));

		$nUrlParts = array();
		$c = 0;
		foreach ($urlParts as $part)
		{
			$part = trim($part, '/');
			if (strlen($part)) $nUrlParts[] = $part;
			else if (sizeof($nUrlParts)) $nUrlParts[] = 'default';
		}

		$urlAnchor = '';
		if (isset($elements['urlAnchor']))
		{
			$urlAnchor = Mozg::Lib('Str')->FullUrlEncode($elements['urlAnchor']);
			unset($elements['urlAnchor']);
		}

		if ($buildParams) $paramsStr = http_build_query($elements, '', '&');
		else
		{
			$paramsStr = false;
			$params = $elements;
		}

		$uri = implode('/', array_reverse($nUrlParts));
		$ext = pathinfo($uri, PATHINFO_EXTENSION);

		$uri = rtrim(_ROOT_URL.$uri, '/');

		if (!$ext)
		{
			$uri .= '/';
		}

		$uri = Mozg::Lib('Str')->FullUrlEncode($uri);

		return $uri.(strlen($paramsStr) ? '?' .$paramsStr : '').(strlen($urlAnchor) ? '#' .$urlAnchor : '');
	}

	public function Modify($elements = array(), $buildParams = true, &$params = array())
	{
		if (is_string($elements)) $elements = $this->ParseUrl($elements);
		return $this->Create(array_merge($_GET, $elements), $buildParams, $params);
	}

	protected function ParseUrl($url)
	{
		$elements = array();
		parse_str($url, $elements);
		return $elements;
	}

	public function CreateInputs($elements = array())
	{
		$inputs = '';

		$elements = (array)$elements;
		foreach ($elements as $name => $value)
		{
			$inputs .= '<input type="hidden" name="' .htmlspecialchars($name). '" value="' .htmlspecialchars($value). '">';
		}

		return $inputs;
	}

	public function Route()
	{
		$request = Mozg::Request('http');
		$requestUri = $request->getRequestUri();

		list ($requestUri) = explode('?', $requestUri);

        $requestUri = trim($requestUri, '/');
        $segments = array();

        if (strlen($requestUri))
        {
	        $segments = explode('/', $requestUri);
			$segments = array_map('urldecode', $segments);
        }

		$elements = $this->Parse($segments);

		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		/**
		 * если остались элементы в segments, значит путь полностью не обработан => ошибка
		 */
		if (sizeof($segments))
		{
			return array($moduleName, false, false);
		}

		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))
		{
			list($ctrlName, $actionName) = $ctrlRouter->DetectCtrlAndAction($elements);
		}

		$_GET = array_merge($_GET, $elements);

		return array($moduleName, $ctrlName, $actionName);
	}

	public function Build(array &$elements = array())
	{
		$urlParts = array();

		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		$urlParts = array_merge($urlParts, (array)$this->GetModuleRouter()->Build($elements));

		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))
		{
			list($ctrlName) = $ctrlRouter->DetectCtrlAndAction($elements);
			$urlParts = array_merge($urlParts, (array)$ctrlRouter->Build($elements));

			if ($ctrlName)
			{
				$buildMethod = 'Build' .$ctrlName;
				if (!method_exists($ctrlRouter, $buildMethod))
				{
					$buildMethod = 'BuildDefault';
				}

				$urlParts = array_merge($urlParts, (array)$ctrlRouter->$buildMethod($elements));
			}
		}

		return $urlParts;
	}

	public function Parse(array &$segments = array())
	{
		$elements = array();
		$elements = array_merge($elements, (array)$this->GetModuleRouter()->Parse($segments));
		$moduleName = $this->GetModuleRouter()->DetectModule($elements);
		if ($ctrlRouter = $this->GetCtrlRouter($moduleName))
		{
			$elements = array_merge($elements, $ctrlRouter->Parse($segments));
			list($ctrlName) = $ctrlRouter->DetectCtrlAndAction($elements);
			if ($ctrlName)
			{
				$parseMethod = 'Parse' .$ctrlName;
				if (!method_exists($ctrlRouter, $parseMethod))
				{
					$parseMethod = 'ParseDefault';
				}

				$elements = array_merge($elements, (array)$ctrlRouter->$parseMethod($segments));
			}
		}

		return $elements;
	}

	public function Redirect($elements = array(), $code = 302)
	{
		//set code to 303 if it used to redirect after post
        Mozg::Response('http')->SetHeader('Cache-Control', 'no-store, no-cache, must-revalidate, post-check=0, pre-check=0, max-age=0', true);
        Mozg::Response('http')->SetHeader('Pragma', 'no-cache', true);
        Mozg::Response('http')->SetHeader('Expires', gmdate('D, d M Y H:i:s', time() - 1000) . ' GMT', true);
		Mozg::Response('http')->setRedirect($this->Create($elements), $code)->sendHeaders();
		exit;
	}
}